#pragma once
#include <cstddef>
#include <tuple>
#include <type_traits>
#include <utility>
#include <vector>
namespace lcir {
/// 将一个可迭代容器映射为一个新的可迭代容器
template <class ItemT, class Func, class VecT>
inline auto mapToVector(const VecT &from, Func f) {
  std::vector<ItemT> ret;
  for (auto &i : from) {
    ret.push_back(f(i));
  }
  return ret;
}

/// 用来从类型获得tuple对应的下标
template <size_t Begin, size_t End, class Tup, class Ty>
constexpr size_t getTupleElementIdx() {
  if constexpr (Begin != End) {
    using type = std::tuple_element_t<Begin, Tup>;
    if (std::is_same_v<type, Ty>)
      return Begin;
    return getTupleElementIdx<Begin + 1, End, Tup, Ty>();
  }
  return End;
}

template <class Tup, class Ty> constexpr size_t getTupleElementIdx() {
  return getTupleElementIdx<0, std::tuple_size_v<Tup>, Tup, Ty>();
}

/// static_for 编译期间静态循环
template <int I> struct constant_int {
  static constexpr int value = I;
};
template <size_t Beg, size_t End, class Lambda>
void static_for(Lambda &&lambda) {
  // std里面的写法
  if constexpr (Beg < End) {
    constant_int<Beg> i;
    lambda(i);
    static_for<Beg + 1, End>(lambda);
  }
}

template <size_t... Is, class Lambda>
void static_for_impl(Lambda &&lambda, std::index_sequence<Is...>) {
  (lambda(std::integral_constant<size_t, Is>{}), ...);
  // std::make_index_sequence<N>() = std::index_sequence<0, 1, 2, 3>
}

template <size_t N, class Lambda> void static_for(Lambda &&lambda) {
  // 生成一个0～N的序列
  static_for_impl(lambda, std::make_index_sequence<N>{});
}

/// TODO: 加个判断确保Ty是一个公共类型
template <class Ty, class... Ts> inline void pushBackPack(std::vector<Ty> &v);
template <class Ty, class T> inline void pushBackPack(std::vector<Ty> &v, T t) {
  v.push_back(t);
}
template <class Ty, class T, class... Ts>
inline void pushBackPack(std::vector<Ty> &v, T t, Ts... ts) {
  v.push_back(t);
  pushBackPack(v, ts...);
}

} // namespace lcir